#include "SingleThreadCMP.h"
#include "../../utils/libcache/Directory.h"

static address_t nil;
static Directory dirEntryNil(1);

SingleThreadCMP::SingleThreadCMP(uint32_t threads,uint32_t lineSize,uint32_t pageSize,
        uint32_t cacheSize) : CMP(threads, pageSize, lineSize, 0)
{
    _cacheSize=cacheSize;
    // 8-way cache
     _cache =  new CacheWriteBack <address_t>  (_cacheSize,8,_lineSize,false,1);
     _cacheHits = new uint32_t [128];
     _cacheMisses = new uint32_t [128];
    reset();
}

SingleThreadCMP::~SingleThreadCMP()
{
    delete _cache;
    delete [] _cacheHits;
    delete [] _cacheMisses;
}

void
SingleThreadCMP::reset()
{
    CMP::reset();
    memset(_cacheHits,0,sizeof(uint32_t)*128);
    memset(_cacheMisses,0,sizeof(uint32_t)*128);
    _tid=_region=0;
}


void
SingleThreadCMP::executeCacheSimulation(Memory *mem,Trace *trace)
{
    uint64_t address=0;
    uint32_t opcode=0;
    uint32_t index=0;
    address_t evict;
    CacheAccess accessResponse;


    while (trace->getMemoryAccess(_tid,index,address,opcode)) {
        index++;
        if (_region!=trace->getRegion(_tid)) {
            _region++;
        }
        if (opcode==LOAD_INST)
            accessResponse=_cache->read2(address,evict,dirEntryNil,dirEntryNil,nil,_tid);
        else
            accessResponse=_cache->write(address,_tid,nil);

        if (CacheAccessIsHit(accessResponse)) {
            _cacheHits[_region]++;
        }
        else {
            _cacheMisses[_region]++;
        }
    }
    std::cout << "End of cache Single Thread CMP simulation"<<std::endl;
}
